/*

 Authors: ZhangXuelian
 	
 
 Changes:
 	
	
*/

#ifndef _COE_SDK_ANDROID_H_
#define _COE_SDK_ANDROID_H_
#include <jni.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <android/log.h> 

#include "./include/coe_lib_api.h"
#include "./include/coe_lib_types.h"
#include "./adlist.h"
#include "./list.h"
#include "coe_sdk_wrapper.h"

// error message
#define	ERROR_OK									0
#define ERROR_UNKNOWN								-1
#define ERROR_NO_IMPLEMENT							-2
#define ERROR_INTERNAL								-3
#define ERROR_BLOCKED								-4
#define ERROR_REQ_TIMEOUT							-5

//	log
#define LOG_TAG "COE_MDM"
#define Debug
#ifdef Debug
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)  
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)  
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)  
#else
#define LOGD(...)
#define LOGI(...)
#define LOGE(...)
#endif

#define my_malloc(size) malloc(size)
#define my_free(p) free(p)
#define my_safe_free(a) { if (a) {my_free(a); a = NULL;} }
#define my_safe_strlen(x) ((x == NULL)?0:strlen(x))

typedef enum MessageType {
	MSGTYPE_CHAT = 2001,
	MSGTYPE_CHAT_ACK = 2002,//单聊应答

	MSGTYPE_GROUPCHAT = 2011,
	MSGTYPE_GROUPCHAT_ACK = 2012,//群聊应答

	MSGTYPE_PUBLICACC = 2021,  //公众号
	MSGTYPE_PUBLICACC_ACK = 2022,  //公众号应答

	MSGTYPE_NOTICE = 2031,	//通知
	MSGTYPE_NOTICE_ACK = 2032,	//通知应答

	MSGTYPE_SYNC = 2041,	//同步
	MSGTYPE_SYNC_ACK = 2042	//同步应答
} MESSAGETYPE;

// 通过Handler记录设备信息关系。免得每个函数都传这三个参数。
typedef struct __tagCommResultData
{
	char * manufacturer_id;
	int product_id;
	char * device_serial_number;
} COMM_DATA;

typedef struct __tag_cmd_receive_data
{
	COMM_DATA comm_data;
	int task_no;
	char * json;
}CMD_RECEIVE_DATA;

typedef struct __tag_cmd_receive_result
{
	COMM_DATA comm_data;
	int task_no;
	char result;
}CMD_RESULT;

typedef struct __tag_record_receive_data
{
	COMM_DATA comm_data;
	char * json;
}RECORD_RECEIVE_DATA;

typedef struct __tagNewDeviceTaskData
{
	COMM_DATA comm_data;
	char * follow_topics;
} NEW_DEVICE_TASK_DATA;

typedef struct __tagCmdSendTaskData
{
	int handler;
	char * json;
	int task_no;
	char priority;
} CMD_SEND_TASK_DATA;

typedef struct __tagRecordSendTaskData
{
	int handler;
	char * json;
	COE_RECORD_TYPE record_type;
	char qos;
	char priority;
} RECORD_SEND_TASK_DATA;

typedef struct __tagImSendTaskData
{
	int cmd;
	char * imid;
	int service_name_len;
	int pb_len;
	char * service_name;
	char * pb_package;
} IM_SEND_TASK_DATA;

typedef enum 
{
	MSG_SDK_WIN_EXIT = 0,	
	MSG_NEW_DEVICE,
	MSG_DELETE_DEVICE,
	MSG_COMMAND_SEND,
	MSG_RECORD_SEND,
	MSG_BASE_IM_SEND,
	// ......
	// device notify
	// 这些消息是内部使用的消息
	MSG_ON_RECEIVE_CMD,        // 接收到了命令
	MSG_ON_RECEIVE_CMD_RESULT ,// 接收到了执行命令的结果
	MSG_ON_RECEIVE_RECORD,     // 接收到了采集记录
	MSG_ON_LOG_MESSAGE,       // Log message.
	MSG_ON_LOGIN_COMPLETE, // 登录完成，通知界面。
	MSG_ON_ONLINE_STATUS,  // 在线状态，通知界面。
	MSG_ON_RECEIVE_BASE_IM_NOTIFY,// 接收到了IM消息。
	MSG_ON_RECEIVE_BASE_MQ_NOTIFY,//接收到了MQ消息
	MSG_ON_IM_ERROR_NOTIFY,	//出错时,通知安卓
	MSG_ON_IM_SDK_INIT_RESULT_NOTIFY,	//sdk init 之后,结果反馈
	MSG_ON_IM_ACTIVE_OFFLINE,	//安卓主动断开连接
} MSG_COMMAND;


typedef struct tagMsg 
{
	MSG_COMMAND command;
	int param1;
	int param2;
	int param3;
	int param4;
	int param5;
	int param6;
	struct list_head list;
} MSG;

typedef struct _IMIDLEN
{
	int sender_imid_len;
	int target_imid_len;
} IMIDLEN;

// init
extern jstring cstr2jstring(JNIEnv * env, char * cstr) ;
extern char * Jstring2CStr( JNIEnv * env, jstring jstr ) ;
extern void init_global_vars_4_javacallback(JNIEnv * env);
extern void deinit_global_vars_4_javacallback(JNIEnv * env);
extern bool init_msg_queue();
extern void deinit_msg_queue();
extern void add_task(MSG_COMMAND command, int param1, int param2, int param3, int param4, int param5, int param6);
extern MSG * get_msg() ;


// str
static __inline unsigned char * mem_new(int value, unsigned int len)
{
	unsigned char * p = (unsigned char *)malloc(len);
	if (! p)
		return NULL;
	memset(p, value, len);
	return p;
}

static __inline unsigned char * mem_assign(const unsigned char * value, unsigned int len)
{
	unsigned char * p = (unsigned char *)malloc(len);	
	if (! p)
		return NULL;
	memcpy(p, value, len);
	return p;
}

static __inline unsigned char * mem_combine(const unsigned char * src1, unsigned int src1_len, const unsigned char * src2, unsigned int src2_len)
{
	unsigned char * p = (unsigned char *)malloc(src1_len + src2_len);
	if (! p)
		return NULL;
	memcpy(p, src1, src1_len);
	memcpy(p + src1_len, src2, src2_len);
	return p;
}

static __inline unsigned char * mem_append(unsigned char * src, unsigned int src_len, const unsigned char * append, unsigned int append_len)
{
	unsigned char * p = mem_combine(src, src_len, append, append_len);
	my_free(src);
	return p;
}

static __inline char * str_assign(const char * value)
{
	return (char *)mem_assign((unsigned char *)value, strlen(value) + 1);
}

static __inline char * str_append(char * src, const char * append)
{
	return (char *)mem_append((unsigned char *)src, strlen(src), (const unsigned char *)append, strlen(append) + 1);
}

static __inline char * str_combine(const char * src1, const char * src2)
{
	return (char *)mem_combine((const unsigned char *)src1, strlen(src1), (const unsigned char *)src2, strlen(src2) + 1);
}

//	Global for JAVA callback
extern JavaVM * g_vm;
extern JNIEnv* g_env;

//sdk回调函数类
extern jclass SdkLibListenerClass;
extern jmethodID OnReceiveCmdMethod;
extern jmethodID OnReceiveCmdResultMethod;
extern jmethodID OnReceiveNotifyMethod;
extern jmethodID OnLogFuncMethod;
extern jmethodID OnLoginCompleteMethod;
extern jmethodID OnOnlineStatusMethod;
extern jmethodID OnAutoSendStatusMethod;
extern jmethodID OnAutoSendRecordMethod;
extern jmethodID OnBaseImProcessNotityMethod;
extern jmethodID OnBaseImProcessNotifyByGroupMethod;
extern jmethodID OnImErrorNotifyMethod;
extern jmethodID OnSdkInitResultNotifyMethod;
extern jmethodID OnBaseImProcessNotifyByNoticeMethod;
extern jmethodID OnBaseImProcessNotifyByPublicAccMethod;
extern jmethodID OnBaseImProcessNotifyBySyncMethod;

// String
extern jclass g_string_class;
extern jmethodID g_string_id;

// AUTO_SEND_RECORD_DATA java class
extern jclass g_auto_send_record_data_class;
extern jfieldID g_cb_json_id;
extern jfieldID g_cb_record_type_id;
extern jfieldID g_cb_qos_id;
extern jfieldID g_cb_priority_id;

//------------------------------------------------------------------------------------------------------------
// 一台具体设备
typedef struct __tagMyDeviceClass
{
	int device_index;       // 累加的设备标志，给外部用。
	char * manufacturer_id;
	int product_id;
	char * device_serial_number;
	COE_CMD_HANDLER * cmd_handler;
	COE_RECORD_HANDLER * record_hander;
}MyDeviceClass;

typedef struct __tag_coe_lib
{
	// for normal data
	COE_DEVICE_NOTIFY device_notify;
	COE_DEVICE_DATA_FUNC device_data_fun;
	coe_log_func log_func;
	// for android sdk
	list * devices;
	jobject sdk_listener; // 包括所有用到的回调函数，如状态集的回调。
	struct list_head msg_queue;
	sem_t msg_sem;
	pthread_mutex_t msg_mutex;
	pthread_t work_thread;
	pthread_t thr_fn_thread;    //为了统一释放线程，add by tqq 2018.10.22  20:40 
	int device_handler;
	bool is_net_ok;
}COE_LIB;

extern COE_LIB g_coe_lib; // for test 
extern bool g_flag_start_once;
extern int g_check_error_code;

typedef struct __init_para
{
	JNIEnv* env;
	jobject thiz;
	jobject listener;
	jstring manufacturer_id;
	jstring manufacturer_license;
	int product_id;
	int product_version;
	jstring device_serial_number;
	jstring device_serial_number_license;
	jstring follow_topics;
	int imid;
	jstring c_server_ip;
	int c_server_port;
}INIT_PARA;

extern INIT_PARA g_init_para;


//	Work Thread
extern void work_thread_handler();
extern bool start_work_thread();
extern void end_work_thread();

// coe_result.c
extern int on_receive_cmd(char * manufacturer_id, int product_id, char * device_serial_number, int task_no, char * json);
extern int on_receive_cmd_result(char * manufacturer_id, int product_id, char * device_serial_number, int task_no, int result);
extern int on_receive_record(char * manufacturer_id, int product_id, char * device_serial_number, char * json);
extern void log_func(int level, const char* module, int line, const char* message);
extern void on_login_complete(int errcode);
extern void on_online_status(int old, int new_status);
extern char * auto_send_status(); // 要求外边实现的，一个自动状态发送。给一个Json给内部。
extern void on_receive_im_msg(int cmd, char* sender_imid, char* target_imid, char * pb_package, int pb_len);
extern void on_receive_mq_msg(int cmd, char * pb_package, int pb_len);
extern void on_im_error_notify(int error_code);
extern void on_im_sdk_init_result_notify(int error_code);
extern AUTO_SEND_RECORD_DATA * auto_send_record(char * manufacturer_id, int product_id, char * device_serial_number); // 要求外边实现的，一个自动记录采集。给一个Json给内部。
extern void handle_msg_on_receive_cmd(JNIEnv* env, MSG * msg);
extern void handle_msg_on_receive_cmd_result(JNIEnv* env, MSG * msg);
extern void handle_msg_on_receive_record(JNIEnv* env, MSG * msg);
extern void handle_msg_on_online_status(JNIEnv* env, MSG * msg);
extern void handle_msg_on_login_complete(JNIEnv* env, MSG * msg);
extern void handle_msg_on_log_message(JNIEnv* env, MSG * msg);
extern void handle_msg_on_receive_base_im_notify(JNIEnv* env, MSG * msg);
extern void handle_msg_on_im_error_notify(JNIEnv* env, MSG * msg);
extern void handle_msg_on_sdk_init_result_notify(JNIEnv* env, MSG * msg);

// coe_cmd.c
extern void handle_msg_base_im_send(JNIEnv* env, MSG * msg);
extern void handle_msg_base_im_active_offline(JNIEnv* env, MSG * msg);
#endif
